package ua.eug.airv1.plane;

import ua.eug.airv1.controllers.ScreenController;
import ua.eug.airv1.map.MapHolder;
import ua.eug.airv1.map.Tile;
import ua.eug.airv1.map.TilePos;
import ua.eug.airv1.orders.EOrder;
import ua.eug.airv1.orders.WeaponOrder;
import ua.eug.airv1.utils.Config;
import ua.eug.airv1.utils.EDirection;
import ua.eug.airv1.weapon.IWeapon;
import ua.eug.airv1.weapon.ZWeapon;

import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;

public abstract class Plane extends Actor implements IWeapon {

	protected TextureRegion texture;
	private final float width = Config.TileWidth;
	private final float heigth = Config.TileHeight;
	private final double tileDistance = Config.TileHeight - 4; // estimate value for "true" hex 
	
	public Boolean alive = false;
	public Boolean landed = false;
	private int owner;
	public EDirection direction;
	public TilePos position;
	protected Tile place = Tile.ZTile;
	protected WeaponOrder order;
	protected Boolean orderDone;
	
	public Plane(int owner, Tile tile) {
		super();
		place = tile;
		tile.setAirWeapon(this);
		setPosition(tile.pos);
		direction = EDirection.N;
		this.owner = owner;
		
		order = new WeaponOrder(this);
		orderDone = false;
	}
		
	@Override
    public void draw(Batch batch, float alpha){
		if (alive)
			batch.draw(texture,getX()-shiftX, getY()+shiftY,
        		width/2,heigth/2, width,heigth, 1,1, getRotation());
    }

	public void setPosition(TilePos xy) {
		this.position = xy;
		this.setPosition();
	}
	
	public void setPosition() {
		Vector2 p = ScreenController.getInstance().XyToStage(position.x, position.y);
		this.setPosition(p.x, p.y);
	}
	
	public WeaponOrder getOrder() {
		return order;
	}
	public EDirection getDirection() {
		return direction;
	}

	// six directions
	public void turn(EDirection dir) {
		direction = dir;
		this.setRotation(dir.getAngle());
	}
	
	//======== IWeapon ====================
	@Override
	public Boolean doAirDamage(IWeapon killer) {
		if (!landed) {
			alive = false;
			place.setAirWeapon(ZWeapon.Nobody);
			place.setExplode(true);
			place = Tile.ZTile;
			return true;
		} else
			return false;
	}

	@Override
	public Boolean doGroundDamage(IWeapon killer) {
		if (landed) {
			alive = false;
			place.setExplode(true);
			place.setGroundWeapon(ZWeapon.Nobody);
			place = Tile.ZTile;
			return true;
		} else
			return false;
	}

	@Override
	public void setTile(Tile t) {
		place = t;
		t.setAirWeapon(this);
		setPosition();
	}

	@Override
	public Tile getTile() {
		return place;
	}

	@Override
	public int getOwner() {
		return owner;
	}

	// Move animation
	private int step = 0;
	private int microstep = 0;
	private float shiftX = 0;
	private float shiftY = 0;
	private float shiftdX = 0;
	private float shiftdY = 0;
	private float tSec = 0;
	protected abstract int getSteps();
	
	@Override
	public Boolean aniMove(float seconds) {
		tSec += seconds;
		if (tSec < 0.1) return true;
		tSec = 0;
		int hexSteps = getSteps(); // set speed according to plane type
		EOrder curr = order.getStep(step);
		if (curr == EOrder.NONE ) {
			// prepare for next game turn
			order.setStep(0,EOrder.NONE ); // Clean order
			step = 0;			
			return false;
		}
		if ( microstep==0 ) { // begin of hex move
			turn(direction.getNext(curr));
			place.setAirWeapon(ZWeapon.Nobody); // leave old place
			
			// calculate step
			
			float distX = (float)(Math.cos( Math.toRadians( direction.getAngle() - 90 ) ) * tileDistance);
			float distY = (float)(Math.sin( Math.toRadians( direction.getAngle() + 90 ) ) * tileDistance);
			shiftdX = distX/hexSteps;
			shiftX = shiftdX;
			shiftdY = distY/hexSteps;
			shiftY = shiftdY;
		} else {
			shiftX += shiftdX;
			shiftY += shiftdY;
		}
				
		if ( ++microstep >= hexSteps) {
			step++;
			microstep = 0;
			shiftX = 0;
			shiftY = 0;
			
			singleHexMove();
		}
		return true;
	}

	private void singleHexMove() {
		position.nextHex(direction);
		
		Tile newTile = MapHolder.getInstance().getTile(position.x, position.y);
		
		// Check crash
		if ( newTile.getAirWeapon().equals( ZWeapon.Nobody ) )
			setTile(newTile);
		else {
			
			// TODO send event to draw explosion
			
			IWeapon enemy = newTile.getAirWeapon();
			enemy.doAirDamage(this);
			place = newTile;
			doAirDamage(enemy);
		}
	}
}
